package cc.sunni.activiti.controller;

import cc.sunni.activiti.config.PropertiesConfig;
import cc.sunni.activiti.mapper.ActivitiMapper;
import cc.sunni.activiti.util.R;
import cn.hutool.core.collection.CollectionUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jl
 * @since 2021/1/28 21:21
 */
@Api(tags = "流程定义管理")
@RequestMapping("/processDefinition")
@RestController
public class ProcessDefinitionController {
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ActivitiMapper activitiMapper;

    @PostMapping("/uploadStream")
    @ApiOperation("上传bpmn文件添加流程定义")
    @ApiImplicitParam(name = "file", value = "bpmn文件", required = true, dataTypeClass = MultipartFile.class)
    public R uploadStream(@RequestParam MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String extension = FilenameUtils.getExtension(originalFilename);
        InputStream inputStream = file.getInputStream();
        if ("bpmn".equals(extension)) {
            Deployment deployment = repositoryService.createDeployment()
                    .addInputStream(originalFilename, inputStream)
                    .deploy();
            return R.ok(deployment.getId());
        }
        return R.error("上传bpmn文件错误");
    }

    @PostMapping(value = "/addDeploymentByString")
    @ApiOperation("在线提交bpmn的xml添加流程定义")
    @ApiImplicitParam(name = "stringBPMN", value = "bpmn的xmlString", required = true, dataTypeClass = String.class)
    public R addDeploymentByString(@RequestParam("stringBPMN") String stringBPMN) {
        Deployment deployment = repositoryService.createDeployment()
                .addString("CreateWithBPMNJS.bpmn", stringBPMN)
                .deploy();
        return R.ok(deployment.getId());
    }

    @GetMapping("/list")
    @ApiOperation(value = "获取流程定义列表")
    public R getDefinitions() {
        List<ProcessDefinition> definitions = repositoryService.createProcessDefinitionQuery().list();
        List<Deployment> deployments = repositoryService.createDeploymentQuery().list();
        Map<String, Date> deploymentsMap = deployments.stream().collect(Collectors.toMap(Deployment::getId, Deployment::getDeploymentTime));
        List<Map<String, Object>> result = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(definitions)) {
            for (ProcessDefinition processDefinition : definitions) {
                Map<String, Object> map = new HashMap<>();
                map.put("id", processDefinition.getId());
                map.put("name", processDefinition.getName());
                map.put("key", processDefinition.getKey());
                map.put("resourceName", processDefinition.getResourceName());
                map.put("deploymentId", processDefinition.getDeploymentId());
                map.put("version", processDefinition.getVersion());
                map.put("deploymentTime", deploymentsMap.get(processDefinition.getDeploymentId()));
                result.add(map);
            }
        }
        return R.ok(result);
    }

    @GetMapping(value = "/getDefinitionXML")
    @ApiOperation("获取流程定义xml")
    public void getProcessDefineXML(@RequestParam("deploymentId") String deploymentId, @RequestParam("resourceName") String resourceName, HttpServletResponse response) throws IOException {
        InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
        int count = inputStream.available();
        byte[] bytes = new byte[count];
        response.setContentType("text/xml");
        OutputStream outputStream = response.getOutputStream();
        while (inputStream.read(bytes) != -1) {
            outputStream.write(bytes);
        }
        inputStream.close();
    }

    @GetMapping(value = "/getDeployments")
    @ApiOperation("获取流程部署列表")
    public R getDeployments() {
        List<HashMap<String, Object>> listMap = new ArrayList<>();
        List<Deployment> list = repositoryService.createDeploymentQuery().list();
        for (Deployment dep : list) {
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("id", dep.getId());
            hashMap.put("name", dep.getName());
            hashMap.put("deploymentTime", dep.getDeploymentTime());
            listMap.add(hashMap);
        }
        return R.ok(listMap);
    }

    @GetMapping(value = "/delDefinition")
    @ApiOperation("删除流程定义")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deploymentId", value = "流程部署ID", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "processDefinitionId", value = "流程定义ID", required = true, dataTypeClass = String.class)})
    public R delDefinition(@RequestParam("deploymentId") String deploymentId, @RequestParam("processDefinitionId") String processDefinitionId) {
        activitiMapper.DeleteFormData(processDefinitionId);
        repositoryService.deleteDeployment(deploymentId, true);
        return R.ok();
    }

    @PostMapping(value = "/upload")
    @ApiOperation("上传bpmn文件到本地")
    @ApiImplicitParam(name = "file", value = "bpmn文件", required = true, dataTypeClass = MultipartFile.class)
    public R upload(@RequestParam("file") MultipartFile multipartFile) throws IOException {
        if (multipartFile.isEmpty()) {
            return R.error("文件为空");
        }
        String fileName = multipartFile.getOriginalFilename();  // 文件名
        String extension = FilenameUtils.getExtension(fileName);
        String filePath = PropertiesConfig.PATH; // 上传后的路径

        fileName = UUID.randomUUID() +"." + extension; // 新文件名
        File file = new File(filePath + fileName);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        multipartFile.transferTo(file);
        return R.ok(fileName);
    }
}
